package ru.compscicenter.uno.view;

import ru.compscicenter.uno.controller.AController;
import ru.compscicenter.uno.log.Logger;
import ru.compscicenter.uno.model.Card;
import ru.compscicenter.uno.model.Model;
import ru.compscicenter.uno.model.ModelException;
import ru.compscicenter.uno.model.Player;
import ru.compscicenter.uno.view.events.DropCardEvent;
import ru.compscicenter.uno.view.events.DropCardListener;
import ru.compscicenter.uno.view.events.TakeCardEvent;
import ru.compscicenter.uno.view.events.TakeCardListener;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Павел
 * Date: 26.11.11
 * Time: 0:59
 * To change this template use File | Settings | File Templates.
 */
public class SwingViewer implements View {
    private final AController controller;
    private int myPlayerId;
    private GameFrame frame;
    private GamePanel gamePanel;

    public SwingViewer(AController c) {
        this.controller = c;
        c.setView(this);

        while (!c.isReady) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Thread updater = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (controller.isChanged()) {
                        controller.setIsChanged(false);
                        if (gamePanel != null) {
                            update();
                        }
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        updater.setDaemon(true);
        updater.start();
    }

    private void update() {
        //Model model = controller.getModel();
        //gamePanel.setModel(controller);
        gamePanel.update();
    }

    public void run() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            System.err.println("Cannot set look & feel style");
        }

        myPlayerId = controller.getModel().getMyPlayerId();
        frame = new GameFrame(controller, controller.isServer());
        gamePanel = frame.getGamePanel();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        gamePanel.getStartNewGameButton().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent event) {
                try {
                    controller.startGame();
                } catch (ModelException e) {
                    JOptionPane.showMessageDialog(frame, "Упс :( Произошла ошибка");
                }
            }
        });

        gamePanel.getStartNewRoundButton().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent event) {
                try {
                    controller.startRound();
                } catch (ModelException e) {
                    JOptionPane.showMessageDialog(frame, "Упс :( Произошла ошибка");
                }
            }
        });

        gamePanel.addTakeCardEventListener(new TakeCardListener() {
            @Override
            public void takeCardEventOccurred(TakeCardEvent evt) {
                try {
                    boolean success = controller.doTakeCard(myPlayerId);
                } catch (ModelException e) {
                    //never thrown by controller
                    Logger.write("Model exception come in SwingViewer o_O : " + e, Logger.Mode.ERROR);
                }
            }
        });

        gamePanel.addDropCardEventListener(new DropCardListener() {
            @Override
            public void dropCardEventOccurred(DropCardEvent evt) {
                CardImage cardImage = evt.getCardImage();
                Card card = evt.getCard();
                boolean success = false;
                try {
                    success = controller.doDropCard(myPlayerId, card.getId(), evt.getColor());
                } catch (ModelException e) {
                    //never thrown by controller
                    Logger.write("Model exception come in SwingViewer o_O : " + e, Logger.Mode.ERROR);
                }
                if (success) {
                    frame.getGamePanel().animateDropCardMyPlayer(cardImage);
                }
            }
        });

        gamePanel.getEndTurnButton().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                controller.doEndTurn(myPlayerId);
            }
        });
    }

    @Override
    public void onDropCard(int playerId, int cardId) {
        System.out.println("player " + playerId + " dropped card " + cardId);
        if (playerId != myPlayerId) {
            gamePanel.animateDropCardOtherPlayer(playerId, cardId);
        }
        Card droppedCard = controller.getTopCard();
        if (droppedCard.getType() == Card.Type.TAKE_TWO) {
            gamePanel.animatePlus2(playerId);
        } else if (droppedCard.getType() == Card.Type.WILD_TAKE_FOUR) {
            gamePanel.animatePlus4(playerId);
        } else if (droppedCard.getType() == Card.Type.SKIP) {
            gamePanel.animateSkip(playerId);
        } else if (droppedCard.getType() == Card.Type.WILD) {
            gamePanel.animateColorChanged();
        } else if (droppedCard.getType() == Card.Type.REVERSE) {
            gamePanel.animateReverse();
        }
    }

    @Override
    public void onDropCard(int playerId, int cardId, Card.Color selectedColor) {
        onDropCard(playerId, cardId);
    }

    @Override
    public void onTakeCard(int playerId) {
        System.out.println("player " + playerId + " took card");
        if (playerId == myPlayerId) {
            gamePanel.animateTakeCardMyPlayer();
        } else {
            gamePanel.animateTakeCardOtherPlayer(playerId);
        }
    }

    @Override
    public void onSayUno(int playerId) {
        gamePanel.animateSayUno(playerId);
    }

    @Override
    public void onSomebodyDidntSayUno(int playerId, int whoDidntSayUnoId) {
        gamePanel.animateDidNotSayUno(whoDidntSayUnoId);
    }

    @Override
    public void onEndTurn(int playerId) {
        gamePanel.animateTurnSwitch(playerId);
    }
}
